/*
 * AESTools.cpp
 *
 *   Created on: 2010-3-27     
 *  Description: 
 *    Copyright: 2010 @ ICT Li Heyuan
 */

#include "../../include/crypto/AESTools.h"
#include <stdexcept>
#include <sstream>
#include <iostream>
#include <ostream>
using std::cout;
using std::endl;
using std::runtime_error;

#include "../../include/util/encode.h"
#include "../../include/util/decode.h"
#include "../../include/util/cencode.h"
#include "../../include/util/cdecode.h"

AESTools::AESTools(const string &key)
{
	//检查key长度
	_key_len = key.size();
	if (_key_len != 16 && _key_len != 24 && _key_len != 32)
	{
		throw runtime_error("key size must be 16/24/32 bytes");
	}

	string::size_type i = 0;
	for (; i < key.size(); i++)
	{
		_key[i] = key[i];
	}

	_rnd.GenerateBlock(_iv, AES::BLOCKSIZE);

/*	cout << _key_len << endl;*/
}

AESTools::AESTools()
{
	_key_len = 0;
}

AESTools::AESTools(const string &key, const string &iv)
{
	//iv进行Base64解码
	/*	std::istringstream in(key_base64);
	 std::ostringstream out;
	 base64::decoder D;
	 D.decode(in, out);
	 string key = out.str();*/

	//检查key长度
	_key_len = key.size();
	if (_key_len != 16 && _key_len != 24 && _key_len != 32)
	{
		throw runtime_error("key size must be 16/24/32 bytes");
	}

	string::size_type i = 0;
	for (; i < key.size(); i++)
	{
		_key[i] = key[i];
	}

	//iv进行Base64解码
	/*	std::istringstream in2(iv_base64);
	 std::ostringstream out2;
	 base64::decoder D2;
	 D2.decode(in2, out2);*/
	//解码后存入_iv
	//	string iv_str = out.str();
	if (iv.size() != sizeof(_iv))
	{
		throw runtime_error("iv is not 16 bytess");
	}
	else
	{
		memcpy(_iv, iv.c_str(), iv.size());
	}
}

AESTools& AESTools::operator =(const AESTools &right)
{
	memcpy(_iv, right._iv, sizeof(right._iv));
	memcpy(_key, right._key, sizeof(right._key));
	this->_key_len = right._key_len;

	return *this;
}

AESTools::~AESTools()
{

}

void AESTools::encrypt(char *plain, unsigned int len)
{

	//加密
	CFB_Mode<AES>::Encryption cfbEncryption(_key, _key_len, _iv);
	cfbEncryption.ProcessData((byte*) plain, (byte*) plain, len);

	return;
}

void AESTools::decrypt(char *cipher, unsigned int len)
{
	//解密
	CFB_Mode<AES>::Decryption cfbDecryption(_key, _key_len, _iv);
	cfbDecryption.ProcessData((byte*) cipher, (byte*) cipher, len);

	return;
}

string AESTools::getIV()
{

	return string((char *) _iv, sizeof(_iv));
}

string AESTools::getKey()
{
	return string((char *) _key, _key_len);
}

string AESTools::encryptWithBase64(const string &plain)
{
	//先加密
	char *cipher_byte = new char[plain.size()];
	strcpy(cipher_byte, plain.c_str());
	encrypt(cipher_byte, plain.size());

	//转化成Base64编码
	string cipher(cipher_byte, plain.size());
	std::istringstream in(cipher);
	std::ostringstream out;
	base64::encoder E;
	E.encode(in, out);

	delete[] cipher_byte;

	return out.str();
}

string AESTools::decryptWithBase64(const string &cipher_b64)
{
	try
	{
		//先base64解码
		std::istringstream in(cipher_b64);
		std::ostringstream out;

		base64::decoder D;
		D.decode(in, out);
		string cipher = out.str();

		//解密
		char *plain_byte = new char[cipher.size()];
		strcpy(plain_byte, cipher.c_str());
		decrypt(plain_byte, cipher.size());
		string plain(plain_byte, cipher.size());
		delete[] plain_byte;

		return plain;
	} catch (runtime_error& err)
	{
/*		cout << err.what();*/
		return string();
	}
}
